#pragma once
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <cstring>
#include <assert.h>
#include <cerrno>
#include <sys/wait.h>
#include <memory>
#include <pthread.h>
#include "ThreadPool/test_6_17/threadPool.hpp"
#include "ThreadPool/test_6_17/log.hpp"
#include "ThreadPool/test_6_17/task.hpp"

void service(int fd, const std::string &client_ip,
             const uint16_t &client_port)
{
    char buffer[1024];
    while (1)
    {
        ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
        if (s > 0)
        {
            buffer[s] = 0;
            std::cout << client_ip << ":" << client_port << "# " << buffer << std::endl;
        }
        else if (s == 0)
        {
            logMessage(ERROR, "%s-%d client close fd,me too!", client_ip.c_str(), client_port);
            break;
        }
        else
        {
            logMessage(FATAL, "read error %d-%s", errno, strerror(errno));
            break;
        }
        write(fd, buffer, strlen(buffer));
    }
    close(fd);
}
// static void service1(int fd, const std::string &client_ip,
//                     const uint16_t &client_port, const std::string &thread_name)
// {
//     char buffer[1024];
//     while (1)
//     {
//         ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
//         if (s > 0)
//         {
//             buffer[s] = 0;
//             std::cout << thread_name<<"|"<<client_ip << ":" << client_port << "# " << buffer << std::endl;
//         }
//         else if (s == 0)
//         {
//             logMessage(ERROR, "%s-%d client close fd,me too!", client_ip.c_str(), client_port);
//             break;
//         }
//         else
//         {
//             logMessage(FATAL, "read error %d-%s", errno, strerror(errno));
//             break;
//         }
//         write(fd, buffer, strlen(buffer));
//     }
//     close(fd);
// }

// static void service(int sock, const std::string &clientip,
//                     const uint16_t &clientport, const std::string &thread_name)
// {
//     // echo server
//     //  同时在线10人
//     //  所以，我们一般服务器进程业务处理，如果是从连上，到断开，要一直保持这个链接, 长连接
//     //  后面有其他方案！
//     char buffer[1024];
//     while (true)
//     {
//         // read && write 可以直接被使用！
//         ssize_t s = read(sock, buffer, sizeof(buffer) - 1);
//         if (s > 0)
//         {
//             buffer[s] = 0; // 将发过来的数据当做字符串
//             std::cout << thread_name << "|" << clientip << ":" << clientport << "# " << buffer << std::endl;
//         }
//         else if (s == 0) // 对端关闭连接
//         {
//             logMessage(NORMAL, "%s:%d shutdown, me too!", clientip.c_str(), clientport);
//             break;
//         }
//         else
//         { //
//             logMessage(ERROR, "read socket error, %d:%s", errno, strerror(errno));
//             break;
//         }

//         write(sock, buffer, strlen(buffer));
//     }
//     close(sock);
// }

// class pthreadData
// {
// public:
//     int _sock;
//     std::string _ip;
//     uint16_t _port;
// };
class tcp_server
{
private:
    const static int gbacklog = 20;

public:
    tcp_server(uint16_t port, std::string ip = "0.0.0.0")
        : _sock(-1), _ip(ip), _port(port), _threadpool_ptr(ThreadPool<Task>::getThreadPool())
    {
    }
    ~tcp_server()
    {
    }
    // static void *Routine(void *args)
    // {
    //     pthread_detach(pthread_self());
    //     pthreadData *pd = (pthreadData *)args;
    //     std::string client_ip = pd->_ip;
    //     uint16_t client_port = pd->_port;
    //     int sock = pd->_sock;
    //     service(sock, client_ip, client_port);
    //     return nullptr;
    // }
    void init()
    {
        // 创建套接字
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_sock < 0)
        {
            logMessage(FATAL, "create socket error %d-%s", errno, strerror(errno));
            exit(2);
        }
        // bind绑定套接字
        struct sockaddr_in local;
        // bzero((void*)&local,sizeof(local));
        memset(&local, 0, sizeof local);
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        inet_pton(AF_INET, _ip.c_str(), &local.sin_addr);
        // local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());
        if (bind(_sock, (struct sockaddr *)&local, (socklen_t)sizeof(local)) < 0)
        {
            logMessage(FATAL, "bind socket error %d-%s", errno, strerror(errno));
            exit(3);
        }
        // 监听
        if (listen(_sock, gbacklog) < 0)
        {
            logMessage(FATAL, "listen socket error %d-%s", errno, strerror(errno));
            exit(4);
        }
        logMessage(NORMAL, "init success,sockfd: %d", _sock);
    }
    void start()
    {
        //_threadpool_ptr->run();
        // signal(SIGCHLD, SIG_IGN); // 对SIGCHLD，主动忽略SIGCHLD信号，子进程退出的时候，会自动释放自己的僵尸状态
        while (true)
        {
            // 建立连接
            struct sockaddr_in src;
            socklen_t len = sizeof(src);
            int fd = accept(_sock, (struct sockaddr *)&src, &len);
            if (fd < 0)
            {
                logMessage(FATAL, "accept error %d-%s", errno, strerror(errno));
                continue;
            }
            uint16_t client_port = ntohs(src.sin_port);
            std::string client_ip = inet_ntoa(src.sin_addr);
            logMessage(NORMAL, "link success, servicesock: %d | %s : %d |\n", fd, client_ip.c_str(), client_port);
            ///////////////////////////////////////////////////////////
            // version3线程池版
            //  Task t(fd, client_ip, client_port, service);
            //  _threadpool_ptr->pushTask(t);

            ////////////////////////////////////////////////////////////
            // version2多线程版
            // pthreadData *pd = new pthreadData();
            // pd->_port = client_port;
            // pd->_sock = fd;
            // pthread_t tid;
            // pthread_create(&tid, nullptr, Routine, pd);

            /////////////////////////////////////////////////////////////
            // version1.1多进程版，使用孙子进程进行服务
            // pid_t id = fork();
            // if (id == 0)
            // {
            //     close(_sock);
            //     if (fork() > 0)
            //         exit(0);
            //     else
            //     {
            //         service(fd, client_ip, client_port);
            //         exit(0);
            //     }
            // }
            // waitpid(id, nullptr, 0);
            // close(fd);

            ////////////////////////////////////////////////////////////////
            // version1.0多进程版，对信号进行忽略
            pid_t id = fork();
            assert(id != -1);
            if (id == 0)
            {
                close(_sock);
                service(fd, client_ip, client_port);
                exit(0);
            }
            close(fd);
        }
    }

private:
    int _sock;
    std::string _ip;
    uint16_t _port;
    std::unique_ptr<ThreadPool<Task>> _threadpool_ptr;
};

// #pragma once

// #include <iostream>
// #include <string>
// #include <unordered_map>
// #include <cstring>
// #include <cerrno>
// #include <cassert>
// #include <signal.h>
// #include <unistd.h>
// #include <memory>
// #include <sys/types.h>
// #include <sys/socket.h>
// #include <arpa/inet.h>
// #include <netinet/in.h>
// #include <sys/wait.h>
// #include <pthread.h>
// #include <ctype.h>
// #include"ThreadPool/test_6_17/threadPool.hpp"
// #include"ThreadPool/test_6_17/log.hpp"
// #include"ThreadPool/test_6_17/task.hpp"

// static void service(int sock, const std::string &clientip,
//                     const uint16_t &clientport, const std::string &thread_name)
// {
//     // echo server
//     //  同时在线10人
//     //  所以，我们一般服务器进程业务处理，如果是从连上，到断开，要一直保持这个链接, 长连接
//     //  后面有其他方案！
//     char buffer[1024];
//     while (true)
//     {
//         // read && write 可以直接被使用！
//         ssize_t s = read(sock, buffer, sizeof(buffer) - 1);
//         if (s > 0)
//         {
//             buffer[s] = 0; // 将发过来的数据当做字符串
//             std::cout << thread_name << "|" << clientip << ":" << clientport << "# " << buffer << std::endl;
//         }
//         else if (s == 0) // 对端关闭连接
//         {
//             logMessage(NORMAL, "%s:%d shutdown, me too!", clientip.c_str(), clientport);
//             break;
//         }
//         else
//         { //
//             logMessage(ERROR, "read socket error, %d:%s", errno, strerror(errno));
//             break;
//         }

//         write(sock, buffer, strlen(buffer));
//     }
//     close(sock);
// }

// class TcpServer
// {
// private:
//     const static int gbacklog = 20;
// public:
//     TcpServer(uint16_t port, std::string ip = "0.0.0.0")
//         : _listensock(-1), _port(port),
//           _ip(ip), _threadpool_ptr(ThreadPool<Task>::getThreadPool())
//     {}
//     void initServer()
//     {
//         // 1. 创建socket -- 进程和文件
//         _listensock = socket(AF_INET, SOCK_STREAM, 0);
//         if (_listensock < 0)
//         {
//             logMessage(FATAL, "create socket error, %d:%s", errno, strerror(errno));
//             exit(2);
//         }
//         logMessage(NORMAL, "create socket success, listensock: %d", _listensock); // 3

//         // 2. bind -- 文件 + 网络
//         struct sockaddr_in local;
//         memset(&local, 0, sizeof local);
//         local.sin_family = AF_INET;
//         local.sin_port = htons(_port);
//         inet_pton(AF_INET, _ip.c_str(), &local.sin_addr);
//         if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
//         {
//             logMessage(FATAL, "bind error, %d:%s", errno, strerror(errno));
//             exit(3);
//         }

//         // 3. 因为TCP是面向连接的，当我们正式通信的时候，需要先建立连接
//         if (listen(_listensock, gbacklog) < 0)
//         {
//             logMessage(FATAL, "listen error, %d:%s", errno, strerror(errno));
//             exit(4);
//         }

//         logMessage(NORMAL, "init server success");
//     }
//     void start()
//     {
//         // signal(SIGCHLD, SIG_IGN); // 对SIGCHLD，主动忽略SIGCHLD信号，子进程退出的时候，会自动释放自己的僵尸状态
//         _threadpool_ptr->run();
//         while (true)
//         {
//             // sleep(1);
//             // 4. 获取连接
//             struct sockaddr_in src;
//             socklen_t len = sizeof(src);
//             // fd(李四，王五等提供服务的服务员) vs _sock(张三 --- 获取新连接)
//             int servicesock = accept(_listensock, (struct sockaddr *)&src, &len);
//             if (servicesock < 0)
//             {
//                 logMessage(ERROR, "accept error, %d:%s", errno, strerror(errno));
//                 continue;
//             }
//             // 获取连接成功了
//             uint16_t client_port = ntohs(src.sin_port);
//             std::string client_ip = inet_ntoa(src.sin_addr);
//             logMessage(NORMAL, "link success, servicesock: %d | %s : %d |\n",
//                        servicesock, client_ip.c_str(), client_port);
//             // verison4 --- 线程池版本
//             Task t(servicesock, client_ip, client_port, service);
//             _threadpool_ptr->pushTask(t);
//         }
//     }
//     ~TcpServer() {}

// private:
//     uint16_t _port;
//     std::string _ip;
//     int _listensock;
//     std::unique_ptr<ThreadPool<Task>> _threadpool_ptr;
// };
